﻿using System;
using System.Collections.Generic;
using System.Diagnostics.Contracts;
using System.Linq;
using System.Text;
using EuroManager.Domain.Simulator.Helpers;

namespace EuroManager.Domain.Simulator.Engine
{
    public abstract class MovingEntity : IMovingEntity
    {
        private Steering steering;

        protected MovingEntity(Vector2D startLocation, float acceleration, float deceleration, float maxSpeed)
        {
            Contract.Requires(acceleration.IsRational() && acceleration >= 0);
            Contract.Requires(deceleration.IsRational() && deceleration >= 0);
            Contract.Requires(maxSpeed.IsRational() && maxSpeed >= 0);

            steering = new Steering(startLocation, acceleration, deceleration, maxSpeed);
        }

        public Vector2D Location
        {
            get { return steering.Location; }
        }

        public float X
        {
            get { return Location.X; }
        }

        public float Y
        {
            get { return Location.Y; }
        }

        public Vector2D Velocity
        {
            get { return steering.Velocity; }
        }

        public Vector2D Direction
        {
            get { return steering.Velocity.Normalized(); }
        }

        public Vector2D Heading
        {
            get { return steering.Heading; }
        }

        public bool IsMoving
        {
            get { return !Velocity.IsZero; }
        }

        public float Speed
        {
            get { return steering.Speed; }
        }

        public virtual void Update(float elapsedTime)
        {
            steering.Update(elapsedTime);
        }

        public float DistanceTo(Vector2D target)
        {
            return (target - Location).Length;
        }

        public float DistanceTo(IMovingEntity entity)
        {
            return DistanceTo(entity.Location);
        }

        public Vector2D DirectionTo(Vector2D target)
        {
            return (target - Location).Normalized();
        }

        public Vector2D DirectionTo(IMovingEntity entity)
        {
            return DirectionTo(entity.Location);
        }

        public void Turn(Vector2D target)
        {
            steering.Turn(target);
        }

        protected void Halt()
        {
            steering.Halt();
        }

        protected void Hit(Vector2D startVelocity)
        {
            steering.Hit(startVelocity);
        }

        protected void Arrive(Vector2D destination, float tolerance)
        {
            steering.Arrive(destination, tolerance);
        }

        protected void Meet(Vector2D destination, float tolerance, float time)
        {
            steering.Meet(destination, tolerance, time);
        }
    }
}
